package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.Type;
import com.ruoyi.system.domain.req.StatisticsOneReq;
import com.ruoyi.system.domain.req.StatisticsThreeReq;
import com.ruoyi.system.domain.req.StatisticsTwoReq;
import com.ruoyi.system.domain.vo.statistics.one.*;
import com.ruoyi.system.domain.vo.statistics.three.StatisticsOne_dept_version1;
import com.ruoyi.system.domain.vo.statistics.three.StatisticsThree;
import com.ruoyi.system.domain.vo.statistics.three.TypeSta_dept;
import com.ruoyi.system.domain.vo.statistics.three.Version1_dept_in;
import com.ruoyi.system.domain.vo.statistics.two.StatisticsTwo;
import com.ruoyi.system.mapper.DeliveryDetailMapper;
import com.ruoyi.system.mapper.DoseDetailMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.TypeMapper;
import com.ruoyi.system.service.TongJiService;
import org.apache.commons.collections4.ListUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

@Service
public class TongJiServiceImpl implements TongJiService {

    @Resource
    private DoseDetailMapper doseDetailMapper;
    @Resource
    private TypeMapper typeMapper;
    @Resource
    private DeliveryDetailMapper deliveryDetailMapper;
    @Resource
    private SysDeptMapper sysDeptMapper;

    /**
     * 各分类总量（月度，季度，年度）
     */
    @Override
    public StatisticsOne_version1 statisticsOne(StatisticsOneReq req) {
        if (req.getSearchType() == null) {
            throw new ServiceException("未选择查询类型");
        }
        List<StatisticsOne> oneList = new ArrayList<>(10);
        String yyyy = DateUtils.dateTimeNow("yyyy");
        //年度，查询这一年的12个月
        if (req.getSearchType() == 2) {
            List<WeekSearch> searchList = getWeekSearchType2(yyyy);
            searchList.forEach(item -> {
                formatWeekSearch(req.getTypeIdList(), null, item);
                List<TypeSta> typeStaS = doseDetailMapper.typeSta(item);
                List<TypeSta> collect = typeStaS.stream().sorted(Comparator.comparing(TypeSta::getCount).reversed()).collect(Collectors.toList());


                oneList.add(new StatisticsOne(item.getStartTime().substring(0, item.getStartTime().lastIndexOf("-")), collect));

            });
        }
        //季度
        else if (req.getSearchType() == 1) {
            List<WeekSearch> searchList = getWeekSearchType1(yyyy);
            for (int i = 0; i < searchList.size(); i++) {
                WeekSearch item = searchList.get(i);
                formatWeekSearch(req.getTypeIdList(), null, item);
                List<TypeSta> typeStaS = doseDetailMapper.typeSta(item);

                oneList.add(new StatisticsOne("第" + (i + 1) + "季度", typeStaS));

            }
        }
        //月度，查询某个月的全部天数
        else if (req.getSearchType() == 0) {
            List<WeekSearch> searchList = getWeekSearchType0(yyyy, req.getMonth());

            searchList.forEach(item -> {
                formatWeekSearch(req.getTypeIdList(), null, item);
                List<TypeSta> typeStaS = doseDetailMapper.typeSta(item);

                List<TypeSta> collect = typeStaS.stream().sorted(Comparator.comparing(TypeSta::getCount).reversed()).collect(Collectors.toList());
                oneList.add(new StatisticsOne(item.getStartTime(), collect));
            });
        }

        StatisticsOne_version1 res = new StatisticsOne_version1();
        res.setKeyList(oneList.stream().map(StatisticsOne::getKey).collect(Collectors.toList()));

        Map<Long, List<KeyCount>> map = new HashMap<>();
        oneList.forEach(item -> {
            List<TypeSta> list1 = item.getList();
            list1.forEach(item_in -> {
                KeyCount in = new KeyCount();
                in.setKey(item.getKey());
                in.setCount(item_in.getCount());
                if (map.containsKey(item_in.getTypeId())) {
                    map.get(item_in.getTypeId()).add(in);
                } else {
                    ArrayList<KeyCount> keyCounts = new ArrayList<>();
                    keyCounts.add(in);
                    map.put(item_in.getTypeId(), keyCounts);
                }
            });
        });

        List<Version1_in> version1_ins = new ArrayList<>();

        map.forEach((key, value) -> {
            Version1_in in = new Version1_in();
            in.setTypeId(key);
            List<KeyCount> keyCounts = map.get(key);
            List<String> collect_key = keyCounts.stream().map(KeyCount::getKey).collect(Collectors.toList());
            List<String> subtract_key = ListUtils.subtract(res.getKeyList(), collect_key);
            subtract_key.forEach(item -> {
                keyCounts.add(new KeyCount(item, BigDecimal.ZERO));
            });
            in.setList(keyCounts.stream().sorted(Comparator.comparing(KeyCount::getKey)).collect(Collectors.toList()));
            version1_ins.add(in);
        });

        Map<Long, Type> typeMap = typeMapper.selectTypeList(new Type()).stream().collect(Collectors.toMap(Type::getId, t -> t));


        List<Version1_in> ten = new ArrayList<>(10);

        //取list前10个
        if (!version1_ins.isEmpty()) {
            for (int i = 0; i < version1_ins.size(); i++) {
                Version1_in element = version1_ins.get(i);
                if (typeMap.containsKey(element.getTypeId())) {
                    element.setTypeName(typeMap.get(element.getTypeId()).getName());
                } else {
                    element.setTypeName("");
                }
                ten.add(element);
                if (i == 10) {
                    break;
                }
            }

        }
        res.setList(ten);


        return res;
    }


    public static LocalDate dateToLocalDate(Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static <T> T getRandomElement(List<T> list) {
        if (list == null || list.isEmpty()) {
            throw new IllegalArgumentException("List cannot be null or empty");
        }

        int index = ThreadLocalRandom.current().nextInt(list.size());

        return list.get(index);
    }

    private List<WeekSearch> getWeekSearchType0(String yyyy, Integer month) {
        List<WeekSearch> searchList = new ArrayList<>();
        LocalDate today = dateToLocalDate(DateUtils.parseDate(yyyy + "-" + month + "-01"));
        //本月的第一天
        LocalDate firstDay = LocalDate.of(today.getYear(), today.getMonth(), 1);
        //本月的最后一天
        LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfMonth());

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<String> betweenDate = DateUtil.getBetweenDate(firstDay.format(formatter), lastDay.format(formatter));

        betweenDate.forEach(item -> {
            searchList.add(new WeekSearch(item, item));
        });
        return searchList;
    }

    private List<WeekSearch> getWeekSearchType1(String yyyy) {
        List<WeekSearch> searchList = new ArrayList<>(4);
        searchList.add(new WeekSearch(yyyy + "-01-01", yyyy + "-03-31"));
        searchList.add(new WeekSearch(yyyy + "-04-01", yyyy + "-06-30"));
        searchList.add(new WeekSearch(yyyy + "-07-01", yyyy + "-09-30"));
        searchList.add(new WeekSearch(yyyy + "-10-01", yyyy + "-12-31"));
        return searchList;
    }

    private List<WeekSearch> getWeekSearchType2(String yyyy) {
        List<WeekSearch> searchList = new ArrayList<>(12);
        searchList.add(new WeekSearch(yyyy + "-01-01", yyyy + "-01-31"));
        searchList.add(new WeekSearch(yyyy + "-02-01", yyyy + "-02-29"));
        searchList.add(new WeekSearch(yyyy + "-03-01", yyyy + "-03-31"));
        searchList.add(new WeekSearch(yyyy + "-04-01", yyyy + "-04-30"));
        searchList.add(new WeekSearch(yyyy + "-05-01", yyyy + "-05-31"));
        searchList.add(new WeekSearch(yyyy + "-06-01", yyyy + "-06-30"));
        searchList.add(new WeekSearch(yyyy + "-07-01", yyyy + "-07-31"));
        searchList.add(new WeekSearch(yyyy + "-08-01", yyyy + "-08-31"));
        searchList.add(new WeekSearch(yyyy + "-09-01", yyyy + "-09-30"));
        searchList.add(new WeekSearch(yyyy + "-10-01", yyyy + "-10-31"));
        searchList.add(new WeekSearch(yyyy + "-11-01", yyyy + "-11-30"));
        searchList.add(new WeekSearch(yyyy + "-12-01", yyyy + "-12-31"));
        return searchList;
    }

    private void formatWeekSearch(List<Long> typeIdList, List<Long> deptIdList, WeekSearch item) {
        if (deptIdList != null && !deptIdList.isEmpty()) {
            item.setDeptIdList(deptIdList);
        }
        if (typeIdList != null && !typeIdList.isEmpty()) {
            item.setTypeIdList(typeIdList);
        }
    }

    /**
     * 各品类供货量环比，同比增长（月度，季度，年度）
     */
    @Override
    public List<StatisticsTwo> statisticsTwo(StatisticsTwoReq req) {
        if (req.getSearchType() == null) {
            throw new ServiceException("未选择查询类型");
        }
        if (req.getRateType() == null) {
            throw new ServiceException("未选择比例类型");
        }
        List<StatisticsTwo> twoList = new ArrayList<>(10);
        String yyyy = DateUtils.dateTimeNow("yyyy");
        //年度
        if (req.getSearchType() == 2) {

        }
        //季度
        else if (req.getSearchType() == 1) {

        }
        //月度
        else if (req.getSearchType() == 0) {

        }
        return Collections.emptyList();
    }

    /**
     * 各个供应商的供货量
     */
    @Override
    public StatisticsOne_dept_version1 statisticsThree(StatisticsThreeReq req) {
        if (req.getSearchType() == null) {
            throw new ServiceException("未选择查询类型");
        }
        List<StatisticsThree> threeList = new ArrayList<>(10);
        String yyyy = DateUtils.dateTimeNow("yyyy");
        //年度
        if (req.getSearchType() == 2) {
            List<WeekSearch> searchList = getWeekSearchType2(yyyy);
            searchList.forEach(item -> {
                if (req.getDeptIdList() != null && !req.getDeptIdList().isEmpty()) {
                    item.setDeptIdList(req.getDeptIdList());
                }
                formatWeekSearch(null, req.getDeptIdList(), item);
                List<TypeSta_dept> typeStaDeptS = deliveryDetailMapper.typeSta_dept(item);
                List<TypeSta_dept> collect = typeStaDeptS.stream().sorted(Comparator.comparing(TypeSta_dept::getCount).reversed()).collect(Collectors.toList());


                threeList.add(new StatisticsThree(item.getStartTime().substring(0, item.getStartTime().lastIndexOf("-")), collect));

            });
        }
        //季度
        else if (req.getSearchType() == 1) {
            List<WeekSearch> searchList = getWeekSearchType1(yyyy);
            for (int i = 0; i < searchList.size(); i++) {
                WeekSearch item = searchList.get(i);
                formatWeekSearch(null, req.getDeptIdList(), item);
                List<TypeSta_dept> typeStaDeptS = deliveryDetailMapper.typeSta_dept(item);

                threeList.add(new StatisticsThree("第" + (i + 1) + "季度", typeStaDeptS));

            }
        }
        //月度
        else if (req.getSearchType() == 0) {
            List<WeekSearch> searchList = getWeekSearchType0(yyyy, req.getMonth());

            searchList.forEach(item -> {
                formatWeekSearch(null, req.getDeptIdList(), item);
                List<TypeSta_dept> typeStaDeptS = deliveryDetailMapper.typeSta_dept(item);

                List<TypeSta_dept> collect = typeStaDeptS.stream().sorted(Comparator.comparing(TypeSta_dept::getCount).reversed()).collect(Collectors.toList());
                threeList.add(new StatisticsThree(item.getStartTime(), collect));
            });
        }


        //转换数据格式
        StatisticsOne_dept_version1 res = new StatisticsOne_dept_version1();
        res.setKeyList(threeList.stream().map(StatisticsThree::getKey).collect(Collectors.toList()));

        Map<Long, List<KeyCount>> map = new HashMap<>();
        threeList.forEach(item -> {
            List<TypeSta_dept> list1 = item.getList();
            list1.forEach(item_in -> {
                KeyCount in = new KeyCount();
                in.setKey(item.getKey());
                in.setCount(item_in.getCount());
                if (map.containsKey(item_in.getDeptId())) {
                    map.get(item_in.getDeptId()).add(in);
                } else {
                    ArrayList<KeyCount> keyCounts = new ArrayList<>();
                    keyCounts.add(in);
                    map.put(item_in.getDeptId(), keyCounts);
                }
            });
        });

        List<Version1_dept_in> version1_ins = new ArrayList<>();

        map.forEach((key, value) -> {
            Version1_dept_in in = new Version1_dept_in();
            in.setDeptId(key);
            List<KeyCount> keyCounts = map.get(key);
            List<String> collect_key = keyCounts.stream().map(KeyCount::getKey).collect(Collectors.toList());
            List<String> subtract_key = ListUtils.subtract(res.getKeyList(), collect_key);
            subtract_key.forEach(item -> {
                keyCounts.add(new KeyCount(item, BigDecimal.ZERO));
            });
            in.setList(keyCounts.stream().sorted(Comparator.comparing(KeyCount::getKey)).collect(Collectors.toList()));
            version1_ins.add(in);
        });

        Map<Long, SysDept> companyMap = sysDeptMapper.selectDeptList(new SysDept() {{
            setType(0);
        }}).stream().collect(Collectors.toMap(SysDept::getDeptId, t -> t));


        List<Version1_dept_in> ten = new ArrayList<>(10);

        //取list前六个
        if (!version1_ins.isEmpty()) {
            for (int i = 0; i < version1_ins.size(); i++) {
                Version1_dept_in element = version1_ins.get(i);
                if (companyMap.containsKey(element.getDeptId())) {
                    element.setDeptName(companyMap.get(element.getDeptId()).getDeptName());
                } else {
                    element.setDeptName("");
                }
                ten.add(element);
                if (i == 6) {
                    break;
                }
            }

        }
        res.setList(ten);
        return res;
    }
}
